package com.liuceng.zen.web.session;

import com.liuceng.zen.web.auth.utils.SerializeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.SimpleSession;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import java.io.Serializable;


/**
 * Created by yanwen on 16-11-17.
 */
@Service
public class SessionRedisDao extends EnterpriseCacheSessionDAO {
    // 保存到Redis中key的前缀 prefix+sessionId
    private String prefix = "";
    private int seconds = 1800;
    private JedisPool jedisPool;

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }
    public void setJedisPool(JedisPool jedisPool) {
        this.jedisPool = jedisPool;
    }
    public void setSeconds(int seconds) {
        this.seconds = seconds;
    }
    private final static Logger SESSION_LOG = LoggerFactory.getLogger("session");

    /**
     * 重写CachingSessionDAO中readSession方法， 如果Session中没有登陆信息就调用doReadSession方法从Redis中重读
     */
    @Override
    public Session readSession(Serializable sessionId) throws UnknownSessionException {
        Session session = super.getCachedSession(sessionId);
        if (session == null
                || session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY) == null) {
            session = this.doReadSession(sessionId);
            if (session == null) {
                SESSION_LOG.info("There is no session with id [" + sessionId + "]");
            } else {
                // 缓存
                cache(session, session.getId());
            }
        }
        return session;
    }
    // 创建session，保存到数据库
    @Override
    protected Serializable doCreate(Session session) {
        Serializable sessionId = super.doCreate(session);
        Jedis jedis = null;
        boolean success=true;
        try {
            jedis = jedisPool.getResource();
            // session由Redis缓存失效决定，这里只是简单标识
            session.setTimeout(seconds);
            jedis.setex(prefix + sessionId.toString(), seconds,
                    SerializeUtils.serializeToString((SimpleSession)session));
            SESSION_LOG.info("sessionId {} name {} 被创建", sessionId, session.getClass().getName());
        } catch (Exception e) {
            SESSION_LOG.info("创建Session失败", e);
            SESSION_LOG.info(e.getMessage(), e);
            success = false;
        } finally {
            if (success && jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
        return sessionId;
    }

    // 获取session
    @Override
    protected Session doReadSession(Serializable sessionId) {
        // 先从缓存中获取session，如果没有再去数据库中获取
        Session session = null; //super.doReadSession(sessionId);

        //if(session==null) {
        Jedis jedis = null;
        boolean success = true;
        try {
            jedis = jedisPool.getResource();
            String key = prefix + sessionId;
            String value = jedis.get(key);
            if (StringUtils.isNotBlank(value)) {
                session = SerializeUtils.deserializeFromString(value);
                SESSION_LOG.info("sessionId {} ttl {}: ", sessionId, value);
                //重置Redis中缓存过期时间
                jedis.expire(key, seconds);
                SESSION_LOG.info("sessionId {} name {} 被读取", sessionId, session.getClass().getName());
            }
        } catch (Exception e) {
            SESSION_LOG.info("读取Session失败 sessionId=" + sessionId, e);
            SESSION_LOG.info(e.getMessage(), e);
            success =false;
        } finally {
            if (success && jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
        /*}*/

        return session;
    }

    // 更新session的最后一次访问时间
    @Override
    protected void doUpdate(Session session) {
        super.doUpdate(session);
        if(session != null ){
            Jedis jedis = null;
            boolean success=true;
            try {
                jedis = jedisPool.getResource();
                String key = prefix + session.getId();
                String value = jedis.get(key);

                if (StringUtils.isNotBlank(value)) {
                    String  sessionSerialize=SerializeUtils.serializeToString((SimpleSession) session);
                    if(sessionSerialize!=null){
                        jedis.setex(prefix + session.getId(), seconds,sessionSerialize );
                        SESSION_LOG.info("更新Session sessionId: {}  name: {} ", session.getId(), session.getClass().getName());
                    }
                }

            } catch (Exception e) {
                SESSION_LOG.info("更新Session失败 sessionId: {} ",session.getId());
                SESSION_LOG.info(e.getMessage(), e);
                success=false;

            }finally {
                if ( success && jedis != null) {
                    jedisPool.returnResource(jedis);
                }
            }
        }
    }

    // 删除session
    @Override
    protected void doDelete(Session session) {
        super.doDelete(session);
        Jedis jedis = null;
        boolean success=true;
        try {
            jedis = jedisPool.getResource();
            // 删除会话
            jedis.del(prefix + session.getId());
            SESSION_LOG.info("Session {} 被删除", session.getId());
        } catch (Exception e) {
            SESSION_LOG.info("删除Session失败", e);
            success = false;
        } finally {
            if (success && jedis != null) {
                jedisPool.returnResource(jedis);
            }

        }
    }

}
